package com.arvinclub.service.config;

import com.arvinclub.model.entity.User;

import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 基于WebSocket的多人聊天室
 */
@ServerEndpoint(value = "/webSocketByTomcat", configurator = GetHttpSessionConfigurator.class)
public class WebSocket {
    /**
     * 聊天室人数
     */
    private static final AtomicInteger onlineCount = new AtomicInteger(0);

    /**
     * 当前聊天室成员
     */
    private static final Map<String, WebSocket> clients = new ConcurrentHashMap<>();

    /**
     * 用户信息
     */
    private Session session;
    private String username;
    private final Object lock = new Object();

    /**
     * 新建连接
     */
    @OnOpen
    public void onOpen(Session session, EndpointConfig config) throws Exception {
        //获取HttpSession，并得到用户名
        HttpSession httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
        username = ((User) httpSession.getAttribute("user")).getName();

        //登录冲突提醒
        if (clients.containsKey(username)) {
            clients.get(username).sendMessageToMe("<span style=\"color:blue\">你已在其他位置登陆</span>");
            clients.get(username).session.close();
        }

        //该用户进入聊天室
        this.session = session;
        clients.put(username, this);

        //聊天室人数调整，并通知其他用户
        onlineCount.set(clients.size());
        sendMessageAll("<span style=\"color:green\">[" + username + "] 进入聊天室, 当前人数: " + getOnlineCount() + "</span>");


    }

    /**
     * 关闭连接
     */
    @OnClose
    public void onClose() throws Exception {

        clients.remove(username);
        onlineCount.set(clients.size());
        sendMessageAll("<span style=\"color:red\">[" + username + "] 离开聊天室, 当前人数: " + getOnlineCount() + "</span>");
        if (session != null && session.isOpen()) {
            session.close();
        }

    }

    /**
     * 处理收到的消息
     */
    @OnMessage
    public void onMessage(String message) throws IOException {
        if (message.equalsIgnoreCase("clear!!!"))
            for (WebSocket webSocket : clients.values())
                webSocket.session.close();
        else if (message.equalsIgnoreCase("num!!!")) {
            sendMessageToMe("<span style=\"color:blue\">当前人数: " + getOnlineCount() + "</span>");
            for (String u : clients.keySet())
                sendMessageToMe("<span style=\"color:blue\">[" + u + "]  </span>");
        } else
            sendMessageAll("[" + username + "]: " + message);
    }

    /**
     * 出错也要保证正常关闭和注销
     */
    @OnError
    public void onError(Throwable error) throws Exception {
        if (session != null && session.isOpen()) {
            session.close();
        }
    }


    /**
     * 广播信息
     */
    private void sendMessageAll(String message) throws IOException {
        for (WebSocket item : clients.values())
            synchronized (item.lock) {
                item.session.getBasicRemote().sendText(message);
            }
    }


    /**
     * 打印出提醒（单人）
     */
    private void sendMessageToMe(String message) throws IOException {
        synchronized (lock) {
            session.getBasicRemote().sendText(message);
        }
    }

    /**
     * 获取当前人数
     */
    public static int getOnlineCount() {
        for (String str : clients.keySet())
            if (!clients.get(str).session.isOpen())
                clients.remove(str);
        return onlineCount.get();
    }

}

